package com.teng.mylibrary.base

import android.annotation.SuppressLint
import android.app.Application
import android.util.Log
import android.view.View
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import com.google.gson.JsonSyntaxException
import com.teng.mylibrary.callback.livedata.event.EventLiveData
import com.teng.mylibrary.entity.BaseResponse
import com.teng.mylibrary.net.ResponseThrowable
import com.teng.mylibrary.net.RxUtil
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import io.reactivex.functions.Consumer
import retrofit2.HttpException
import java.net.ConnectException
import java.net.NoRouteToHostException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import javax.net.ssl.SSLHandshakeException

/**
 * 作者　: liuteng
 * 时间　: 2019/12/12
 * 描述　: ViewModel的基类
 */
open class BaseViewModel : ViewModel(),
    IBaseViewModel, Consumer<Disposable> {

    /**
     * 管理RxJava,主要针对RxJava异步操作造成的内存泄露
     * */
    private var mCompositeDisposable: CompositeDisposable = CompositeDisposable()

    val uc: UiChangeLiveData by lazy { UiChangeLiveData() }

    @SuppressLint("CheckResult")
    protected fun <T> requestData(code: Int, observer: Observable<BaseResponse<T>>) {
        observer.compose(RxUtil.schedulersTransformer())
            .compose(RxUtil.exceptionTransformer())
            .doOnSubscribe(this)
            .doOnSubscribe {
                uc.showDialogEvent.call()
            }
            .subscribe({ it: BaseResponse<T> ->
                if (it.result.errorCode == 0) {
                    returnData(code, it.data)
                } else {
                    returnError(code, it.result.msg)
                    uc.showProTextEvent.postValue(it.result.msg)
                }
            } as ((Any) -> Unit)?, { throwable ->
                val exception = throwable as ResponseThrowable
                uc.dismissDialogEvent.call()
                returnError(code, exception.message.toString())
                uc.showProTextEvent.postValue(exception.message)
                Log.e("cnn", "=========" + throwable.localizedMessage)
            }, {
                uc.dismissDialogEvent.call()
            })
    }

    protected open fun <T> returnData(apiCode: Int, dataEntity: T?) {

    }

    protected open fun returnError(apiCode: Int, errMsg: String?) {

    }

    protected open fun initData() {

    }

    override fun onAny(owner: LifecycleOwner?, event: Lifecycle.Event?) {
    }

    override fun onCreate() {
        //获取一次数据
        initData()
    }

    override fun onDestroy() {
    }

    override fun onStart() {
    }

    override fun onStop() {
    }

    override fun onResume() {
    }

    override fun onPause() {
    }

    override fun onCleared() {
        super.onCleared()
        mCompositeDisposable.clear()
    }

    override fun accept(t: Disposable?) {
        mCompositeDisposable.add(t!!)
    }

    /**
     * 内置封装好的可通知Activity/fragment 显示隐藏加载框
     */
    inner class UiChangeLiveData {
        //显示加载框
        val showDialogEvent by lazy { EventLiveData<Void>() }

        //隐藏加载框
        val dismissDialogEvent by lazy { EventLiveData<Void>() }

        //显示单项提示框
        val showProTextEvent by lazy { EventLiveData<String>() }

        //显示Toast 成功提示框
        val showToastOkEvent by lazy { EventLiveData<String>() }

        //显示Toast 失败提示框
        val showToastOtherEvent by lazy { EventLiveData<String>() }

        //重置表头数据
        val headerNotify by lazy { EventLiveData<Void>() }

        //结束当前页
        val finishPageEvent by lazy { EventLiveData<Void>() }

        //显示空数据页面
        val showEmptyView by lazy { EventLiveData<Void>() }

        //显示数据页面
        val showDataView by lazy { EventLiveData<Void>() }

        //上拉刷新
        val refreshComplete by lazy { EventLiveData<Void>() }

        //下拉加载
        val loadMoreComplete by lazy { EventLiveData<Void>() }

        //隐藏键盘
        val hideKeyboard by lazy { EventLiveData<View>() }


    }
}